{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "8e3qhaan0Vwx"
   },
   "source": [
    "# Analyzing Quantum Volume Errors\n",
    "This notebook analyzes the error rates required for achieving Quantum Volume at a particular depth. For a given m = depth = number of qubits, plot the HOG for np.logspace outputs to view when it crosses the 2/3rds probability threshold."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "bd9529db1c0b"
   },
   "outputs": [],
   "source": [
    "try:\n",
    "    import cirq\n",
    "except ImportError:\n",
    "    print(\"installing cirq...\")\n",
    "    !pip install --quiet cirq\n",
    "    print(\"installed cirq.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "1QezTbjO0Vw4"
   },
   "outputs": [],
   "source": [
    "import cirq\n",
    "import cirq_google\n",
    "\n",
    "# Configuration parameters. Feel free to mess with these!\n",
    "num_circuits = 10\n",
    "depth = 4\n",
    "num_samplers = 50\n",
    "repetitions = 10_000\n",
    "device = cirq_google.Sycamore\n",
    "\n",
    "print(f\"Configuration: depth {depth} with \" f\"{num_circuits} circuits of {num_samplers} samplers\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "rZ_7U7n90Vw5"
   },
   "outputs": [],
   "source": [
    "# Run the Quantum Volume algorithm over the above parameters.\n",
    "\n",
    "import numpy as np\n",
    "from cirq.contrib import quantum_volume, routing\n",
    "\n",
    "errors = np.logspace(-1, -4, num=num_samplers)\n",
    "samplers = [\n",
    "    cirq.DensityMatrixSimulator(\n",
    "        noise=cirq.ConstantQubitNoiseModel(qubit_noise_gate=cirq.DepolarizingChannel(p=error))\n",
    "    )\n",
    "    for error in errors\n",
    "]\n",
    "\n",
    "\n",
    "def optimize(circuit):\n",
    "    return cirq.optimize_for_target_gateset(circuit, gateset=cirq.SqrtIswapTargetGateset())\n",
    "\n",
    "\n",
    "result = quantum_volume.calculate_quantum_volume(\n",
    "    num_circuits=num_circuits,\n",
    "    depth=depth,\n",
    "    num_qubits=depth,\n",
    "    device_graph=routing.gridqubits_to_graph_device(device.metadata.qubit_set),\n",
    "    samplers=samplers,\n",
    "    compiler=optimize,\n",
    "    repetitions=repetitions,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "CvJvkMLx0Vw6"
   },
   "outputs": [],
   "source": [
    "# Create a chart that plots the HOG rate relative to the simulated error ratio.\n",
    "\n",
    "from matplotlib import pyplot as plt\n",
    "import statistics\n",
    "\n",
    "\n",
    "def chunks(l, n):\n",
    "    \"\"\"Yield successive n-sized chunks from l.\"\"\"\n",
    "    for i in range(0, len(l), n):\n",
    "        yield l[i : i + n]\n",
    "\n",
    "\n",
    "split = chunks([res.sampler_result for res in result], num_circuits)\n",
    "fig, axs = plt.subplots()\n",
    "axs.plot(errors, [statistics.mean(chunk) for chunk in split])\n",
    "\n",
    "# Line markers for asymptotic ideal heavy output probability and the ideal Heavy\n",
    "# Output Generation threshold.\n",
    "axs.axhline((1 + np.log(2)) / 2, color='tab:green', label='Asymptotic ideal', linestyle='dashed')\n",
    "axs.axhline(2 / 3, label='HOG threshold', color='k', linestyle='dotted')\n",
    "plt.xscale('log')\n",
    "axs.set_ybound(0.4, 1)\n",
    "axs.set_xlabel(\"error rate\")\n",
    "axs.set_ylabel(\"est. heavy output probability\")\n",
    "fig.suptitle(f'HOG probability by simulated error rate for d={depth}')"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "name": "quantum_volume_errors.ipynb",
   "toc_visible": true
  },
  "kernelspec": {
   "display_name": "Python 3",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
